#include <iostream>
#include <utility>

#include "GLee.h"
#include <GL/glu.h>

#include "OptionsScreen.h"
#include "MainMenu.h"
#include "MyWindow.h"
#include "Button.h"
#include "FontManager.h"
#include "Background.h"
#include "AudioSource.h"
#include "CheckButton.h"
#include "ChkButtonBar.h"
#include "FreeTypeFont.h"

#define BAR_SIZE     10

using namespace std;

OptionsScreen::OptionsScreen(MyWindow* window)
: Scene(window), m_easyBtn(NULL), m_mediumBtn(NULL), m_hardBtn(NULL), m_okBtn(NULL),
m_cancelBtn(NULL), m_background(NULL), m_bgm(NULL), m_localOptions(), m_musicBar(NULL), m_sfxBar(NULL)
{
}

OptionsScreen::~OptionsScreen(void)
{
}

bool OptionsScreen::init()
{
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);

    //Viewport[2] stores the width of the viewport, vieport[3] stores the height
    //We pass these into our font so the ortho mode can set the resolution for the window
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    // Initialize the font
    FontManager* fontManager = FontManager::getInstance();
    if (fontManager->hasFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 60)))
    {
        m_font = fontManager->getFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 60));
    }
    else
    {
        m_font = boost::shared_ptr<FreeTypeFont>(new FreeTypeFont("data/textures/ANGRY_BIRDS.ttf",
                              viewport[2], 
                              viewport[3], 
                              60));
        fontManager->addFont(m_font);
    }

    // Initialize the font
    if (fontManager->hasFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 36)))
    {
        m_font2 = fontManager->getFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 36));
    }
    else
    {
        m_font2 = boost::shared_ptr<FreeTypeFont>(new FreeTypeFont("data/textures/ANGRY_BIRDS.ttf",
                              viewport[2], 
                              viewport[3], 
                              36));
        fontManager->addFont(m_font2);
    }

    // Initialize the background
    m_background = new Background("data/textures/background8.tga");
    if (!m_background->initialize()) {
        std::cerr << "Could not initialize the background" << std::endl;
        return false;
    }

    // Initialize EASY button
    m_easyBtn = new Button(boost::shared_ptr<Scene>(this));
    m_easyBtn->setDimension(Dimension(148.0f, 42.0f));
    m_easyBtn->setPosition(Vector3(430.0f, 390.0f, 0.0f));
    if (!m_easyBtn->initialize()) {
        std::cerr << "Could not initialize the EASY Button" << std::endl;
        return false;
    }
    m_easyBtn->setFontSize(24);
    m_easyBtn->setLabel("EASY ");

    // Initialize MEDIUM button
    m_mediumBtn = new Button(boost::shared_ptr<Scene>(this));
    m_mediumBtn->setDimension(Dimension(148.0f, 42.0f));
    m_mediumBtn->setPosition(Vector3(590.0f, 390.0f, 0.0f));
    if (!m_mediumBtn->initialize()) {
        std::cerr << "Could not initialize the MEDIUM Button" << std::endl;
        return false;
    }
    m_mediumBtn->setFontSize(24);
    m_mediumBtn->setLabel("MEDIUM ");

    // Initialize HARD button
    m_hardBtn = new Button(boost::shared_ptr<Scene>(this));
    m_hardBtn->setDimension(Dimension(148.0f, 42.0f));
    m_hardBtn->setPosition(Vector3(750.0f, 390.0f, 0.0f));
    if (!m_hardBtn->initialize()) {
        std::cerr << "Could not initialize the HARD Button" << std::endl;
        return false;
    }
    m_hardBtn->setFontSize(24);
    m_hardBtn->setLabel("HARD ");

    // Initialize local options according to global options
    GameOptions* globalOpt = GameOptions::getOptions();
    m_localOptions.m_difficulty = globalOpt->difficulty();
    m_localOptions.m_musicLevel = globalOpt->musicLevel();
    m_localOptions.m_sfxLevel = globalOpt->sfxLevel();

    // Activate button according to previous game options
    switch(m_localOptions.m_difficulty)
    {
    case EASY:
        m_easyBtn->setButtonState(ACTIVE);
        break;
    case MEDIUM:
        m_mediumBtn->setButtonState(ACTIVE);
        break;
    case HARD:
        m_hardBtn->setButtonState(ACTIVE);
        break;
    default:
        break;
    }

    // Initialize OK button
    m_okBtn = new Button(boost::shared_ptr<Scene>(this));
    m_okBtn->setDimension(Dimension(100.0f, 42.0f));
    m_okBtn->setPosition(Vector3(750.0f, 50.0f, 0.0f));
    if (!m_okBtn->initialize()) {
        std::cerr << "Could not initialize the OK Button" << std::endl;
        return false;
    }
    m_okBtn->setFontSize(24);
    m_okBtn->setLabel("OK ");

    // Initialize CANCEL button
    m_cancelBtn = new Button(boost::shared_ptr<Scene>(this));
    m_cancelBtn->setDimension(Dimension(100.0f, 42.0f));
    m_cancelBtn->setPosition(Vector3(860.0f, 50.0f, 0.0f));
    if (!m_cancelBtn->initialize()) {
        std::cerr << "Could not initialize the CANCEL Button" << std::endl;
        return false;
    }
    m_cancelBtn->setFontSize(24);
    m_cancelBtn->setLabel("CANCEL ");

    // Initialize the music level check buttons bar
    m_musicBar = new ChkButtonBar(boost::shared_ptr<Scene>(this), BAR_SIZE);
    if (!m_musicBar->initialize(Dimension(30.0f, 30.0f),
                                Vector3(400.0f, 275.0f, 0.0f),
                                Vector3(35.0f, 0.0f, 0.0f)))
    {
        std::cerr << "Could not initialize the music level bar" << std::endl;
        return false;
    }
    m_musicBar->setValue(m_localOptions.m_musicLevel);

    // Initialize the SFX level check buttons bar
    m_sfxBar = new ChkButtonBar(boost::shared_ptr<Scene>(this), BAR_SIZE);
    if (!m_sfxBar->initialize(Dimension(30.0f, 30.0f),
                              Vector3(400.0f, 205.0f, 0.0f),
                              Vector3(35.0f, 0.0f, 0.0f)))
    {
        std::cerr << "Could not initialize the SFX level bar" << std::endl;
        return false;
    }
    m_sfxBar->setValue(m_localOptions.m_sfxLevel);

    // Initialize the background music
    m_bgm = new AudioSource(string("bgm_main_menu"), MUSIC);
    m_bgm->setAudioFile("data/audio/main_menu.ogg");
    m_bgm->setLoop(true);
    m_bgm->initialize();
    m_bgm->setVolume(globalOpt->musicLevel());
    m_bgm->play();


    return true;
}

void OptionsScreen::prepare(float dt)
{
    // Update buttons
    m_easyBtn->prepare(dt);
    m_mediumBtn->prepare(dt);
    m_hardBtn->prepare(dt);
    m_okBtn->prepare(dt);
    m_cancelBtn->prepare(dt);
    
    // Update music level bar
    m_musicBar->prepare(dt);
    m_localOptions.m_musicLevel = m_musicBar->getValue();

    // Update sfx level bar
    m_sfxBar->prepare(dt);
    m_localOptions.m_sfxLevel = m_sfxBar->getValue();

    // Check if EASY button has been pressed
    if (m_easyBtn->isClicked())
    {
        m_easyBtn->setClicked(false);
        m_localOptions.m_difficulty = EASY;
        m_easyBtn->setButtonState(ACTIVE);
        m_mediumBtn->setButtonState(IDLE);
        m_hardBtn->setButtonState(IDLE);
    }
    // Check if MEDIUM button has been pressed
    else if (m_mediumBtn->isClicked())
    {
        m_mediumBtn->setClicked(false);
        m_localOptions.m_difficulty = MEDIUM;
        m_easyBtn->setButtonState(IDLE);
        m_mediumBtn->setButtonState(ACTIVE);
        m_hardBtn->setButtonState(IDLE);
    }
    // Check if HARD button has been pressed
    else if (m_hardBtn->isClicked())
    {
        m_hardBtn->setClicked(false);
        m_localOptions.m_difficulty = HARD;
        m_easyBtn->setButtonState(IDLE);
        m_mediumBtn->setButtonState(IDLE);
        m_hardBtn->setButtonState(ACTIVE);
    }

    // Check if OK button has been pressed
    if (m_okBtn->isClicked())
    {
        GameOptions* globalOpt = GameOptions::getOptions();
        globalOpt->setOptions(m_localOptions);
        m_nextScene = new MainMenu(m_window);
        m_bgm->stop();
    }
    // Check if CANCEL button has been pressed
    else if (m_cancelBtn->isClicked())
    {
        m_nextScene = new MainMenu(m_window);
        m_bgm->stop();
    }
}

void OptionsScreen::render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //Load the identity matrix (reset to the default position and orientation)
    glLoadIdentity();

    // Render background
    m_background->render();

    // Render title
    m_font->printString("GAME OPTIONS", 
                        (m_screenSize.width / 2.0f) - 185.0f, 
                        (m_screenSize.height / 2.0f) + 190.0f);

    // Render difficulty buttons
    m_font2->printString("DIFFICULTY", 130.0f, 375.0f);
    m_easyBtn->render();
    m_mediumBtn->render();
    m_hardBtn->render();

    // Render global buttons
    m_okBtn->render();
    m_cancelBtn->render();

    // Render music level bar
    m_font2->printString("MUSIC LEVEL", 130.0f, 255.0f);
    m_musicBar->render();

    // Render music level bar
    m_font2->printString("SFX LEVEL", 130.0f, 185.0f);
    m_sfxBar->render();

}

void OptionsScreen::shutdown()
{
    m_bgm->stop();
    m_nextScene = NULL;
}

void OptionsScreen::onResize(int width, int height)
{
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0, width, 0, height, -1, 1);
    m_screenSize.width = static_cast<float> (width);
    m_screenSize.height = static_cast<float> (height);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


